﻿#region Using Directives

using System.Collections.Generic;

using GalaSoft.MvvmLight;

using Scripni.Chess.Core.BoardModels;
using Scripni.Chess.Core.Pieces;

#endregion

namespace Scripni.Chess.UI.ViewModels
{
    /// <summary>
    /// Represents a chess board view model.
    /// </summary>
    public class BoardViewModel : ViewModelBase
    {
        #region Constructors

        /// <summary>
        /// Creates a new instance of the <see cref="BoardViewModel"/> class.
        /// </summary>
        /// <param name="initializationMode"></param>
        public BoardViewModel(BoardInitializationMode initializationMode)
        {
            this.squares = CreateSquares();
            if (initializationMode == BoardInitializationMode.InitialPosition)
            {
                SetInitialPosition(this.squares);
            }
            else if (initializationMode == BoardInitializationMode.Empty)
            {
                //do nothing
            }
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the chess board as a list of board squares.
        /// </summary>
        public IEnumerable<BoardSquareViewModel> Squares
        {
            get
            {
                //invert rows vertically, white is at the bottom
                for (int i = 7; i >= 0; i--)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        yield return squares[i, j];
                    }
                }
            }
        }

        #endregion

        #region Private Methods

        private static BoardSquareViewModel[,] CreateSquares()
        {
            var squares = new BoardSquareViewModel[Board.BoardSize,Board.BoardSize];
            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    squares[i, j] =
                        new BoardSquareViewModel(new BoardPosition(i, j));
                }
            }
            return squares;
        }

        private static void SetInitialPosition(BoardSquareViewModel[,] squares)
        {
            //add pawns
            for (int i = 0; i < 8; i++)
            {
                squares[1, i].Piece = new WhitePawn();
                squares[6, i].Piece = new BlackPawn();
            }

            //add rooks
            squares[0, 0].Piece = new Rook(PieceColor.White);
            squares[0, 7].Piece = new Rook(PieceColor.White);
            squares[7, 0].Piece = new Rook(PieceColor.Black);
            squares[7, 7].Piece = new Rook(PieceColor.Black);

            //add knights
            squares[0, 1].Piece = new Knight(PieceColor.White);
            squares[0, 6].Piece = new Knight(PieceColor.White);
            squares[7, 1].Piece = new Knight(PieceColor.Black);
            squares[7, 6].Piece = new Knight(PieceColor.Black);

            //add bishops
            squares[0, 2].Piece = new Bishop(PieceColor.White);
            squares[0, 5].Piece = new Bishop(PieceColor.White);
            squares[7, 2].Piece = new Bishop(PieceColor.Black);
            squares[7, 5].Piece = new Bishop(PieceColor.Black);

            //add queens
            squares[0, 3].Piece = new Queen(PieceColor.White);
            squares[7, 3].Piece = new Queen(PieceColor.Black);

            //add kings
            squares[0, 4].Piece = new King(PieceColor.White);
            squares[7, 4].Piece = new King(PieceColor.Black);
        }

        #endregion

        #region Constants and Fields

        private readonly BoardSquareViewModel[,] squares;

        #endregion
    }

    /// <summary>
    /// Enumerates possible chess board initialization modes.
    /// </summary>
    public enum BoardInitializationMode
    {
        /// <summary>
        /// Board is initialized with empty squares.
        /// </summary>
        Empty = 0,

        /// <summary>
        /// Board is initialized with all pieces at their initial positions.
        /// </summary>
        InitialPosition
    }
}